import router from '@/router'
import appStore from '@/store'
import dataSources from '@/api'
import plugins from './plugins'
import log from './utils/sys-utils/log'
import statistics from './utils/sys-utils/statistics'
import injectApp from './indexhandler/injectApp'
import cmlpanel from '@/assets/js/app/cmlpanel'
import cmlGlobal from '@/assets/js/app/cmlpanel/util/cmlGlobal'
import { default as panelServer } from '@/assets/js/app/cmlpanel/panelServer'
import * as anov from 'anov-core'
import * as fullScreen from './utils/sys-utils/fullScreen'
import { remove, set } from 'lodash'
import { msg, notice, modal, confirm } from '@/assets/js/app/message'
import { isPlainObject, isArray } from 'dtc'
import { setConfig } from './utils/sys-utils/setConfig'
import loading from './indexhandler/loading.js'
import EventType from './indexhandler/appEvent'
import configHandler from './indexhandler/configHandler'
import validateHandler from './indexhandler/validateHandler'
import * as adapt from './indexhandler/pageAdapt'
import wsInit, { connectWebsocket } from './utils/sys-utils/ws_manager'
import { codeInjection } from '@/assets/js/app/utils/sys-utils/codeInjection.js'
import { handlerHotkeyConfig } from '@/assets/js/app/utils/sys-utils/handleHotkeyConfig.js'

let __begTime = new Date()

const app = {
  isInit: false,
  cmlpanel, //控制面板
  panelServer,
  plugins, //系统插件
  loading,
  modal,
  setConfig,
  msg,
  notice,
  confirm,
  systemRun: false,
  log,
  ...adapt,
  EventType,
  config: { autoInit: true, isAnimate: true },
  control: {},
  anovPart: {},
  casheData: [],
  ...anov.runtimeServer.getEventBus(),
  ...anov, //可视化服务引擎
  ...cmlGlobal,
  ...fullScreen, //全屏控制
  init({ to, from, next }) {
    app.control = { to, from, next }
    let events = app.EventType
    for (let key in events) {
      let value = events[key]
      let handler = app[value]
      app.$on(events[key], handler)
    }
    app.$emit(app.EventType.storeInit)
  },
  //_______________________________________________

  // 数据更新
  dataUpdate(path = 'xxx', key = 'xxx.xxx', val = 'xxx') {
    let args = [...arguments]
    let data = args[0]
    if (isPlainObject(data) && data.path) {
      for (let i = 0; i < app.casheData.length; i++) {
        let casheData = app.casheData[i]
        if (casheData.path == data.path) {
          app.casheData[i] = data
          if (data.path == app.control.to.path) {
            appStore.commit('UPDATE_DATASET_OBJ', data)
            app.$emit(app.EventType.dataUpdate, { path: data.path })
            console.log('数据已更新')
          }
          break
        }
      }
      return
    }
    if (args.length < 2) {
      console.error('app.dataUpdate-参数输入有误,数据更新失败')
      return
    }
    if (args.length == 2) {
      path = app.control.to.path
      key = args[0]
      val = args[1]
    }
    let pageData = app.casheData.find((item) => item.path == path)
    if (pageData) {
      set(pageData, key, val)
      if (path == app.control.to.path) {
        appStore.commit('UPDATE_DATASET', { key, val })
        app.$emit(app.EventType.dataUpdate, { path, key })
        console.log('数据已更新')
      }
    } else {
      console.error('app.dataUpdate-参数输入有误,数据更新失败')
      return
    }
  },
  setServerConfig(config) {
    app.initConfig(config)
  },
  // 数据销毁
  dataDestroy() {
    app.casheData && (app.casheData = [])
  },
  // 部署数据
  deploymentData() {
    let path = app.control.to.path
    let dataSet = app.casheData.find((v) => v.path == path)
    if (dataSet) {
      appStore.commit('setDataSet', dataSet)
      app.$emit(app.EventType.dataReady)
    } else {
      console.error('app.deploymentData error-数据格式有误')
    }
  },
  // 数据更新
  __onAppDataUpdate(msg) {
    console.log(msg)
  },
  initConfig(config = {}) {
    app.log('__onAppConfigInit')
    // app.loading.add('appConfig')
    configHandler.$on(configHandler.event.configMergeEnd, (config) => {
      Object.assign(app.config, config)
      app.$emit(app.EventType.licenseValidate)
    })
    configHandler.init(config)
  },
  //_______________________________________________________________
  __onAppResourceLoad() {
    app.log('__onAppResourceLoad')
  },
  __onAppStoreInit() {
    app.log('__onAppStoreInit')
    // app.loading.add('appStore')
    app.runtimeServer.setAppStore(appStore)
    app.$emit(app.EventType.configInit)
  },
  __onAppConfigInit() {},
  // 内核服务初始化
  __onAppCoreServerInit() {
    let config = app.config
    app.log('__onAppCoreServerInit')
    // app.loading.add('appCore')
    //预加载
    app.preloadServer.init(config)
    //系统环境
    app.envServer.init(config)
    //数据源服务
    app.dataSourceServer.init(config)
    app.dataSourceServer.addDataSources(dataSources)
    app.api = app.dataSourceServer.create()
    // 页面服务
    app.pageServer.init(config.page)
    // 基础组件服务
    app.partServer.init(config.part)
    // 音效服务
    app.soundServer.init(config.soundServer)
    // 动画服务
    app.animateServer.init(config.animateConfig)
    //动作服务
    app.actionServer.init(config)
    app.actionServer.addActions(config.actions)
    //语音合成服务
    app.voiceFeedbackServer.init(config)
    //语音识别服务
    app.voiceRecognizeServer.init(config)
    app.voiceRecognizeServer.addCommands(config.commands)
    //人脸识别服务
    app.faceRecognizeServer.init(config)
    //手势识别
    app.gestureRecognizeServer.init(config)
    //快捷键服务
    app.hotkeyServer.init(config)

    let hotkeyConfig = handlerHotkeyConfig(config.hotkeys)
    app.hotkeyServer.addHotkeys(hotkeyConfig)
    // 控制面板
    app.panelServer.init(config.panel)
    // 光感服务
    app.lightSensorServer.init(config)
    //主题服务
    app.themeServer.init(config.theme)
    // i18n
    app.languageServer.init(config.language)
    // 系统自检
    app.systemCheckServer.init(config)
    // 聚焦模式
    app.focusServer.init(config.focus)
    // app ready
    app.$emit(app.EventType.ready)

    //显示loadingWarn
    app.loading._showLoadingWarn()
    //存储大屏等级
    app.envServer.level = __ANOV__ENV.level
  },
  __onApplicenseValidate() {
    //授权服务
    app.log('__onApplicenseValidate')
    validateHandler.$on(validateHandler.event.licensePass, (e) => {
      // app.loading.add('anovCore')
      app.$emit(app.EventType.coreServerInit)
      const chipType = appStore.state.env.chip
      let headLess = window.navigator.userAgent
        .toLowerCase()
        .indexOf('headless')
      if (chipType === 'remote' && headLess === -1) {
        // 连接ws服务器
        wsInit(app.config.remote)
        const serverPath = app.config.admin.serverPath
        const code = app.adminServer.code
        connectWebsocket(serverPath, __ANOV__ENV.projectId, code)
          .then((wsEvent) => {
            const type = wsEvent.type
            let envState = type === 'open' ? true : false
            appStore.commit('env/setIsConnectCapacityServer', envState)
            appStore.commit('remote/OPEN')
          })
          .catch((err) => {
            console.warn(`Error connecting to the server ${err}`)
            appStore.commit('env/setIsConnectCapacityServer', false)
            appStore.commit('remote/CLOSE')
          })
      }
    })
    validateHandler.licenseValidate(app.config)
  },
  __onAppReady() {
    // 页面适配
    app.adaptApp_init()
    app.adaptModal_init()
    // app.loading.add('dataInit')
    app.log('__onAppReady app加载时间' + (new Date() - __begTime) + 'ms')
    // // app.loading.add('')
    app.isInit = true
    app.$emit(app.EventType.loginValidate)
    // added by WUYAX @2021-07-26
    if (process.env.NODE_ENV == 'development') {
      const { w, h } = app.envServer.designSize
      const routes = app.pageServer.routes
        .filter((route) => route.path !== '*')
        .map((item) => item.path)
      app.adminServer._init_screenshot_params({
        width: w,
        height: h,
        projectId: window.__ANOV__ENV.projectId,
        projectCode: appStore.state.env.customer.info.code,
        router: {
          mode: router.mode,
          routes
        }
      })
    }
  },
  __onAppLoginValidate() {
    app.log('__onAppLoginValidate')
    validateHandler.$on(validateHandler.event.noNeedLogin, (e) => {
      app.$emit(app.EventType.beforePageEnter, app.control)
    })
    validateHandler.$on(validateHandler.event.loginSuccess, (e) => {
      app.$emit(app.EventType.beforePageEnter, app.control)
    })
    validateHandler.loginValidate(app.config)
  },
  __onAppBeforePageEnter(e) {
    app.control = e //页面进入前，页面控制control 改变
    app.log('beforePageEnter')

    //跳过anov2默认的api数据调用生命周期
    app.$emit(app.EventType.dataReady)
    return
    // app.loading.add('beforePageEnter')
    let path = app.control.to.path
    let dataSet = app.casheData.find((v) => v.path == path)
    if (dataSet && !dataSet.__dataForce) {
      appStore.commit('setDataSet', dataSet)
      app.$emit(app.EventType.dataReady)
    } else {
      remove(app.casheData, (item) => item.path == path)

      app.api?.init()
    }
  },
  __onAppDataInit(anovData) {
    app.log('dataInit')
    let data
    if (anovData.data && anovData.force) {
      data = anovData.data
    } else {
      data = anovData
    }
    if (isArray(data)) {
      anovData.force &&
        data.forEach((item) => {
          item.__dataForce = anovData.force
        })
      app.casheData.push(...data)
      app.deploymentData()
    } else if (isPlainObject(data)) {
      anovData.force && (data.__dataForce = anovData.force)
      app.casheData.push(data)
      app.deploymentData()
    } else {
      console.error('app.EventType.dataInit error-参数格式传入有误')
    }
  },
  __onAppDataReady() {
    app.log('dataReady')
    // app.loading.add('dataReady')
    if (app.control.runtime) {
      app.anovPage.update()
      app.control.runtime = false
      return
    }
    app.control?.next()
  },
  __onAppPageEnter(e) {
    app.log('pageEnter')
    app.pageServer.handleInfo(e)
  },
  __onAppPageReady() {
    app.log('pageReady')
    if (app.loading.state == 'show') {
      app.loading._toFinished()
    } else {
      app.anovPage.enter()
    }
  },
  __onAppPageTlStart() {
    app.log(`pageTlStart`)
  },
  __onAppPageTlEnd() {
    app.log(`pageTlEnd`)
    !app.systemRun && app.envServer.addInfo('system run success')
    app.systemRun = true
    setTimeout(() => {
      app.envServer.initStatus()
      // added by WUYAX @2022-01-11
      if (app.adminServer.ws && app.adminServer.ws.readyState === 1) {
        const dom = app.envServer.getState().dom
        app.adminServer.ws
          .sendCustomize({ dom, routeName: app.anovPage.$route.name }, 'DOM')
          .catch(() => undefined)
      }
      const myEvent = new CustomEvent('app-ready', {
        detail: null
      })
      window.dispatchEvent(myEvent)
    }, 3000)
  },
  __onAppPageLeave(e) {
    app.control = e //页面离开，页面控制control 改变
    app.log('pageLeave')
    app.anovPage.leave(app.control)
    app.anovPart = {} //清空anovPart 对象
  }
}
injectApp({ router, app })
export default app
